Skip to content

Beacon API 是一种用于在浏览器中异步发送数据的 Web API。它通常用于在页面关闭前发送一些数据,以确保这些数据不会因为页面的关闭而丢失。

1. 工作机制

当用户关闭页面后,浏览器会执行一些幕后工作,比如关闭页面相关资源、清理页面状态,还有比如检查是否有未发送的Beacon请求,并尝试去发送请求,这些都是在后台线程进行,所以并不会阻碍页面的关闭。

而 Beacon API 正是因为浏览器这种后台机制,使得页面关闭后依然可以发送请求。

2. 特点

  1. 异步非阻塞

调用接口后,无需等待服务器响应,而是把网络请求加入队列,不会影响页面代码执行和用户体验。 加入队列后,浏览器会等网络空闲进行请求,不影响页面中其它资源的网络传输

  1. 数据缓存

加入队列后,需要发送的数据将被缓存起来,从而避免页面关闭造成数据丢失

  1. 支持多种数据格式

允许发送的数据格式有String、ArrayBuffer、TypedArray、DataView、ReadableStream、Blob、FormData对象和URLSearchParams

  1. 请求结果无通知和提示

静默执行,请求成功或失败,浏览器都不会有提示

3. 适用场景

  1. 数据监控分析

性能监控,分析用户浏览行为,统计页面停留时间等

  1. 日志记录

当页面崩溃时,发送相关数据,以便重现场景方便调试

  1. 实时传输数据

ajax请求会占用网络带宽,影响用户体验,而Beacon可以在不影响用户体验前提下,异步发送这些数据

4. 如何使用

1. 接口参数

navigator.sendBeacon(url, [data])

  • url: 请求地址,必填参数
  • data: 传送数据,支持的格式见上文

接口执行后返回布尔值,表示是否成功插入队列

2. 例子

最常见的提交JSON数据

js
const url = '/postTest'
const data = {
    a: 1,
    b: 2
}
navigator.sendBeacon(url, JSON.stringify(data))

需要说明的是请求只支持POST方式,如使用express做后端的话,相关代码为

js
const express = require('express')
const app = express()

const bodyParser = require('body-parser')
app.use(bodyParser.text())
app.use(bodyParser.urlencoded({extended: false}))

app.post('/postTest', (req, res) => {
  // do something
  console.log(req.body)
})

3. 取消请求

先说结论,Beacon无法取消请求,除非浏览器关闭

起初以为sendBeacon基于fetch,所以尝试使用AbortController取消请求,网上搜了一下还真有这种资料

navigator.sendBeacon(url, data, options),第三个参数为 { credentials: 'include', signal: abortController.signal }

其中 signal 支持传入AbortSignal对象,用于取消请求

补充一下,AbortSignal 是一个用于取消异步操作的信号对象,与AbortController一起使用,常用于fetch的取消请求

axois的底层其实也是基于fetch,所以也可以使用AbortController来取消请求

然后我就写了测试代码,在 Chrome v123 下,完全无效,无法取消请求

js
// 创建一个 AbortController 对象
const controller = new AbortController()
const signal = controller.signal

const url = '/postTest'
const data = {
    a: 1,
    b: 2
}

// 请求任务增加信号传参
navigator.sendBeacon(url, JSON.stringify(data), { signal: controller.signal })

setTimeout(() => {
    controller.abort()
    console.log('请求已取消')
}, 100)

5.兼容性

综上所述,Beacon API 主要取决于需求和使用场景。如果需要获取大量数据或者处理复杂的网络请求,Fetch API 可能更适合你的需求;而如果只需要发送少量数据,并且不影响用户体验,或希望在页面关闭时也能够发送数据,Beacon API 可能更适合你。

上次更新于: